#include "tetris.h"
#include <QPainter>
#include <QRandomGenerator>

Tetris::Tetris(QWidget *parent) : QWidget(parent), timer(new QTimer(this)), board(BoardHeight, QVector<int>(BoardWidth, 0)) {
    connect(timer, &QTimer::timeout, this, &Tetris::gameLoop);
    timer->start(500); // 方块下降速度
    spawnBlock();
}

Tetris::~Tetris() {
    delete timer;
}

void Tetris::paintEvent(QPaintEvent *event) {
    QPainter painter(this);

    // 绘制背景
    painter.fillRect(rect(), Qt::black);

    // 绘制棋盘
    for (int y = 0; y < BoardHeight; ++y) {
        for (int x = 0; x < BoardWidth; ++x) {
            if (board[y][x]) {
                painter.fillRect(x * BlockSize, y * BlockSize, BlockSize, BlockSize, Qt::blue);
            }
        }
    }

    // 绘制当前方块
    for (const QPoint &p : currentBlock.shape) {
        int x = currentBlock.position.x() + p.x();
        int y = currentBlock.position.y() + p.y();
        painter.fillRect(x * BlockSize, y * BlockSize, BlockSize, BlockSize, Qt::red);
    }
}

void Tetris::keyPressEvent(QKeyEvent *event) {
    Block movedBlock = currentBlock;

    switch (event->key()) {
    case Qt::Key_Left:
        movedBlock.position.rx() -= 1;
        break;
    case Qt::Key_Right:
        movedBlock.position.rx() += 1;
        break;
    case Qt::Key_Down:
        movedBlock.position.ry() += 1;
        break;
    case Qt::Key_Up:
        movedBlock.rotate();
        break;
    default:
        QWidget::keyPressEvent(event);
        return;
    }

    if (!isColliding(movedBlock)) {
        currentBlock = movedBlock;
        update();
    }
}

void Tetris::gameLoop() {
    Block movedBlock = currentBlock;
    movedBlock.position.ry() += 1;

    if (isColliding(movedBlock)) {
        lockBlock();
        clearFullLines();
        spawnBlock();
        if (isColliding(currentBlock)) {
            timer->stop(); // 游戏结束
        }
    } else {
        currentBlock = movedBlock;
    }

    update();
}

void Tetris::clearFullLines() {
    for (int y = BoardHeight - 1; y >= 0; --y) {
        if (std::all_of(board[y].begin(), board[y].end(), [](int cell) { return cell != 0; })) {
            board.removeAt(y);
            board.prepend(QVector<int>(BoardWidth, 0));
            y++;
        }
    }
}

bool Tetris::isColliding(const Block &block) {
    for (const QPoint &p : block.shape) {
        int x = block.position.x() + p.x();
        int y = block.position.y() + p.y();

        if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight) {
            return true;
        }

        if (board[y][x]) {
            return true;
        }
    }

    return false;
}

void Tetris::lockBlock() {
    for (const QPoint &p : currentBlock.shape) {
        int x = currentBlock.position.x() + p.x();
        int y = currentBlock.position.y() + p.y();
        board[y][x] = 1;
    }
}

void Tetris::spawnBlock() {
    currentBlock = Block();
    currentBlock.position = {BoardWidth / 2, 0};
}
